﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;

namespace AdornerTest
{
	/// <summary>
	/// An overlay for selected items on the canvas that shows four size handles, and a central move handle
	/// Took the start of this from the internets.
	/// </summary>
	public class SimpleCircleAdorner : Adorner
	{
		[Flags]
		private enum ThumbHandles
		{
			None = 0,
			TopLeft = 1,
			Top = 2,
			TopRight = 4,
			Right = 8,
			BottomRight = 16,
			Bottom = 32,
			BottomLeft = 64,
			Left = 128,
			All = TopLeft | Top | TopRight | Right | BottomRight | Bottom | BottomLeft | Left
		}

		Dictionary<ThumbHandles, Thumb> _dicThumbs = null;

		// Adorner requires a UIElement constructor
		public SimpleCircleAdorner(UIElement adornedElement)
		  : base(adornedElement)
		{
			Double thumbSize = 8;
			_children = new VisualCollection(this);
			_dicThumbs = new Dictionary<ThumbHandles, Thumb>();
			CreateThumbs(thumbSize);
		}

		/// <summary>
		/// Create four corners and center handle
		/// </summary>
		/// <param name="thumbSize"></param>
		private void CreateThumbs(double thumbSize)
		{
			_dicThumbs.Add(ThumbHandles.TopLeft, CreateThumb(thumbSize, thumbSize, Brushes.CornflowerBlue, Cursors.SizeNWSE, ThumbHandles.TopLeft));
			_dicThumbs.Add(ThumbHandles.TopRight, CreateThumb(thumbSize, thumbSize, Brushes.CornflowerBlue, Cursors.SizeNESW, ThumbHandles.TopRight));
			_dicThumbs.Add(ThumbHandles.BottomLeft, CreateThumb(thumbSize, thumbSize, Brushes.CornflowerBlue, Cursors.SizeNESW, ThumbHandles.BottomLeft));
			_dicThumbs.Add(ThumbHandles.BottomRight, CreateThumb(thumbSize, thumbSize, Brushes.CornflowerBlue, Cursors.SizeNWSE, ThumbHandles.BottomRight));
			_dicThumbs.Add(ThumbHandles.All, CreateThumb(thumbSize, thumbSize, Brushes.CornflowerBlue, Cursors.SizeAll, ThumbHandles.All));
			_dicThumbs[ThumbHandles.TopLeft].DragDelta += SimpleCircleAdorner_DragDelta;
			_dicThumbs[ThumbHandles.TopRight].DragDelta += SimpleCircleAdorner_DragDelta;
			_dicThumbs[ThumbHandles.BottomLeft].DragDelta += SimpleCircleAdorner_DragDelta;
			_dicThumbs[ThumbHandles.BottomRight].DragDelta += SimpleCircleAdorner_DragDelta;
			_dicThumbs[ThumbHandles.All].DragDelta += SimpleCircleAdorner_DragDelta;
		}

		/// <summary>
		/// Thumbs are easily moved, and give you a DragDelta so you know how far they moved.
		/// The thumbs are the corners of the adorner and center.
		/// </summary>
		private void SimpleCircleAdorner_DragDelta(object sender, DragDeltaEventArgs e)
		{
			FrameworkElement elt = this.AdornedElement as FrameworkElement;
			if (elt != null)
			{
				Thumb t = sender as Thumb;
				SomeItem i = elt.DataContext as SomeItem;
				if (t != null && i != null)
				{

					ThumbHandles th = (ThumbHandles)t.Tag;
					switch (th)
					{
						case ThumbHandles.None:
							break;
						case ThumbHandles.TopLeft:
							{
								double w = elt.ActualWidth - e.HorizontalChange;
								double h = elt.ActualHeight - e.VerticalChange;
								if (w > 0)
								{
									i.Left = i.Left + e.HorizontalChange;
									i.Width = i.Width - e.HorizontalChange;
								}
								if (h > 0)
								{
									i.Top = i.Top + e.VerticalChange;
									i.Height = i.Height - e.VerticalChange;
								}
								break;
							}
						case ThumbHandles.Top:
							break;
						case ThumbHandles.TopRight:
							{
								double w = elt.ActualWidth + e.HorizontalChange;
								double h = elt.ActualHeight - e.VerticalChange;
								if (w > 0)
								{
									i.Width = w;
									i.Top = i.Top + e.VerticalChange;
								}
								if (h > 0)
								{
									i.Height = h;
								}
								break;
							}
						case ThumbHandles.Right:
							break;
						case ThumbHandles.BottomRight:
							{
								double w = elt.ActualWidth + e.HorizontalChange;
								double h = elt.ActualHeight + e.VerticalChange;
								if (w > 0)
								{
									i.Width = w;
								}
								if (h > 0)
								{
									i.Height = h;
								}
								break;
							}
						case ThumbHandles.Bottom:
							break;
						case ThumbHandles.BottomLeft:
							{
								double w = elt.ActualWidth - e.HorizontalChange;
								double h = elt.ActualHeight + e.VerticalChange;
								if (w > 0)
								{
									i.Left = i.Left + e.HorizontalChange;
									i.Width = i.Width - e.HorizontalChange;
								}
								if (h > 0)
								{
									i.Height = i.Height + e.VerticalChange;
								}
								break;
							}
						case ThumbHandles.Left:
							break;
						case ThumbHandles.All:
							{

								if (i != null)
								{
									i.Left = i.Left + e.HorizontalChange;
									i.Top = i.Top + e.VerticalChange;
								}
								break;
							}
						default:
							break;
					}
				}
			}
		}

		private Thumb CreateThumb(double width, double height, Brush color, Cursor cursor, ThumbHandles whatCorner)
		{

			Thumb result = new Thumb();
			result.Width = width;
			result.Height = height;
			result.Background = color;
			result.Cursor = cursor;
			result.Tag = whatCorner;
			_children.Add(result);
			return result;
		}

		protected override Size ArrangeOverride(Size finalSize)
		{
			// position the thumbs around the element
			double tWidth = _dicThumbs[ThumbHandles.TopLeft].Width;
			double tHeight = _dicThumbs[ThumbHandles.TopLeft].Height;
			double TopPlusOffset = -2 - tHeight;
			double BottomPlusOffset = this.DesiredSize.Height + 2;
			double RightPlusOffset = this.DesiredSize.Width + 2;
			double LeftPlusOffset = -2 - tWidth;
			double cX = (this.DesiredSize.Width - 4.0) / 2.0;
			double cY = (this.DesiredSize.Height - 4.0) / 2.0;


			_dicThumbs[ThumbHandles.TopLeft].Arrange(new Rect(LeftPlusOffset, TopPlusOffset, _dicThumbs[ThumbHandles.TopLeft].Width, _dicThumbs[ThumbHandles.TopLeft].Height));
			_dicThumbs[ThumbHandles.TopRight].Arrange(new Rect(RightPlusOffset, TopPlusOffset, _dicThumbs[ThumbHandles.TopLeft].Width, _dicThumbs[ThumbHandles.TopLeft].Height));
			_dicThumbs[ThumbHandles.BottomLeft].Arrange(new Rect(LeftPlusOffset, BottomPlusOffset, _dicThumbs[ThumbHandles.TopLeft].Width, _dicThumbs[ThumbHandles.TopLeft].Height));
			_dicThumbs[ThumbHandles.BottomRight].Arrange(new Rect(RightPlusOffset, BottomPlusOffset, _dicThumbs[ThumbHandles.TopLeft].Width, _dicThumbs[ThumbHandles.TopLeft].Height));
			_dicThumbs[ThumbHandles.All].Arrange(new Rect(cX, cY, _dicThumbs[ThumbHandles.TopLeft].Width, _dicThumbs[ThumbHandles.TopLeft].Height));

			return finalSize;
		}


		VisualCollection _children;
		protected override int VisualChildrenCount
		{
			get
			{
				return this._children.Count;
			}
		}

		protected override Visual GetVisualChild(int index)
		{
			return this._children[index];
		}
	}
}
